﻿using System;
using System.Collections.ObjectModel;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using CommunityToolkit.Mvvm.ComponentModel;
using OxyPlot;
using OxyPlot.Axes;
using OxyPlot.Legends;
using OxyPlot.Series;
using Ops.Exchange.Management;
using Ops.Host.App.Models;
using Ops.Host.Core.Management;
using static FreeSql.Internal.GlobalFilter;

namespace Ops.Host.App.ViewModels;

public sealed class KibanaViewModel : ObservableObject, IDisposable
{
    private readonly CancellationTokenSource _cts = new();

    private readonly DeviceInfoManager _deviceInfoManager;
    private readonly DeviceHealthManager _deviceHealthManager;

    /// <summary>
    /// 定时器处理对象
    /// </summary>
    public EventHandler? TimerHandler { get; set; }

    public KibanaViewModel(
        DeviceInfoManager deviceInfoManager,
        DeviceHealthManager deviceHealthManager)
    {
        _deviceInfoManager = deviceInfoManager;
        _deviceHealthManager = deviceHealthManager;

        Init();
    }

    void Init()
    {
        var deviceInfos = _deviceInfoManager.GetAll();
        foreach (var deviceInfo in deviceInfos)
        {
            DeviceSourceList.Add(new KibanaModel
            {
                Line = deviceInfo.Schema.Line,
                Station = deviceInfo.Schema.Station,
                ConnectedState = false,
            });
        }

        // 初始化能耗图
        InitEnergyChart();

        // 监听消息
        _ = Task.Factory.StartNew(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                var (ok, msg) = await MessageTaskQueueManager.Default.WaitDequeueAsync();
                if (!ok)
                {
                    break;
                }

                switch (msg!.Code)
                {
                    case MessageClassify.Alarm:
                        AddAlarmMessage(msg);
                        break;
                    case MessageClassify.SpotCheck:
                        AddSpotCheckMessage(msg);
                        break;
                    case MessageClassify.Energy:
                        AddEnergyMessage(msg);
                        break;
                    case MessageClassify.CardSwiping:
                        AddCardSwipingMessage(msg);
                        break;
                    default:
                        break;
                }
            }
        }, default, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());

        // 状态检测
        _deviceHealthManager.Check();
        _ = Task.Factory.StartNew(async () =>
        {
            while (!_cts.IsCancellationRequested)
            {
                await Task.Delay(2000);
                ChangeDeviceConnState();
            }

        }, default, TaskCreationOptions.LongRunning, TaskScheduler.FromCurrentSynchronizationContext());

        // 测试
        //_ = Task.Factory.StartNew(async () =>
        //{
        //    int n = 0;
        //    double sum = 0;
        //    while (!_cts.IsCancellationRequested)
        //    {
        //        n++;

        //        var msg1 = new Message("OP002", MessageClassify.Alarm, $"夹具电压过高警报-{n}");
        //        await MessageTaskQueueManager.Default.QueueAsync(msg1);

        //        sum += new Random().Next(1, 100);
        //        var msg2 = new Message("OP002", MessageClassify.Energy, (n%2).ToString(), sum);
        //        await MessageTaskQueueManager.Default.QueueAsync(msg2);

        //        for (int i = 0; i < 5; i++)
        //        {
        //            var msg3 = new Message("OP002", MessageClassify.SpotCheck, $"夹具电压过高警报-{n}", (i + n) % 3 == 0);
        //            await MessageTaskQueueManager.Default.QueueAsync(msg3);
        //        }

        //        await Task.Delay(2000);
        //    }
        //}, default, default, TaskScheduler.FromCurrentSynchronizationContext());
    }

    #region 绑定属性

    private ObservableCollection<KibanaModel> _deviceSourceList = new();

    public ObservableCollection<KibanaModel> DeviceSourceList
    {
        get => _deviceSourceList; 
        set => SetProperty(ref _deviceSourceList, value);
    }

    #region 警报

    private ObservableCollection<AlarmModel> _alarmSourceList = new();

    public ObservableCollection<AlarmModel> AlarmSourceList
    {
        get => _alarmSourceList;
        set => SetProperty(ref _alarmSourceList, value);
    }

    private void AddAlarmMessage(Message msg)
    {
        // 超过指定数量，移除最后一条数据。
        if (AlarmSourceList.Count >= 32)
        {
            AlarmSourceList.RemoveAt(AlarmSourceList.Count - 1);
        }

        // 插入数据到起始位置（UI 上倒序显示）。
        AlarmSourceList.Insert(0, new()
        {
            Station = msg.Station,
            Name = msg.Name,
        });
    }

    #endregion

    #region 点检

    private ObservableCollection<SpotCheckModel> _spotChecskSourceList = new();

    public ObservableCollection<SpotCheckModel> SpotCheckSourceList
    {
        get => _spotChecskSourceList;
        set => SetProperty(ref _spotChecskSourceList, value);
    }

    private void AddSpotCheckMessage(Message msg)
    {
        // 超过指定数量，移除最后一条数据。
        if (SpotCheckSourceList.Count >= 32)
        {
            SpotCheckSourceList.RemoveAt(SpotCheckSourceList.Count - 1);
        }

        // 插入数据到起始位置（UI 上倒序显示）。
        var (item, pass) = ((string?, bool))msg.Value!;
        SpotCheckSourceList.Insert(0, new()
        {
            Station = msg.Station,
            Tooling = msg.Name,
            Name = item,
            IsPass = pass!,
        });
    }

    #endregion

    #region 刷卡

    private ObservableCollection<CardSwipingModel> _cardSwipingModelSourceList = new();

    public ObservableCollection<CardSwipingModel> CardSwipingModelSourceList
    {
        get => _cardSwipingModelSourceList;
        set => SetProperty(ref _cardSwipingModelSourceList, value);
    }

    private void AddCardSwipingMessage(Message msg)
    {
        // 超过指定数量，移除最后一条数据。
        if (CardSwipingModelSourceList.Count >= 32)
        {
            CardSwipingModelSourceList.RemoveAt(CardSwipingModelSourceList.Count - 1);
        }

        // 插入数据到起始位置（UI 上倒序显示）。
        var (cardDevice, owner) = ((string?, string?))msg.Value!;
        CardSwipingModelSourceList.Insert(0, new()
        {
            Station = msg.Station,
            CardNo = msg.Name,
            Owner = owner,
            CardDevice = cardDevice,
        });
    }

    #endregion

    #region 能耗

    public PlotModel EnergyPlotModel { get; } = new() 
    {
        TitleFontSize = 14,
        TitleFontWeight = FontWeights.Normal,
        TitleColor = OxyColors.Green,
        Title = "能耗累计数据",
    };

    private void AddEnergyMessage(Message msg)
    {
        var energy = (float?)msg.Value;
        if (energy == null)
        {
            return;
        }

        var series =(LineSeries?)EnergyPlotModel.Series.FirstOrDefault(s => s.Title == LineSeriesKey(msg.Station, msg.Name));
        if (series == null)
        {
            return;
        }

        if (series.Points.Count >= 16)
        {
            series.Points.RemoveAt(0);
        }

        series.Points.Add(new DataPoint(DateTimeAxis.ToDouble(DateTime.Now), energy.Value));
        EnergyPlotModel.InvalidatePlot(true); // 实时更新数据
    }

    private void InitEnergyChart()
    {
        // X轴
        var dateAxis = new DateTimeAxis()
        {
            MajorGridlineStyle = LineStyle.Automatic,
            MinorGridlineStyle = LineStyle.Dot,
            StringFormat = "MM/dd HH:mm", // 日期格式
            Angle = 15,
            //IntervalLength = 60,
            IsZoomEnabled = false,
            IsPanEnabled = false,
        };
        EnergyPlotModel.Axes.Add(dateAxis);

        // Y轴
        var valueAxis = new LinearAxis()
        {
            MajorGridlineStyle = LineStyle.Solid,
            MinorGridlineStyle = LineStyle.Dot,
            IntervalLength = 20,
            //Angle = 20,
            IsZoomEnabled = false,
            IsPanEnabled = false,
        };
        EnergyPlotModel.Axes.Add(valueAxis);

        // 添加 Legend
        var legend = new Legend
        {
            LegendPlacement = LegendPlacement.Outside,
        };
        EnergyPlotModel.Legends.Add(legend);

        // 添加数据曲线
        foreach (var item in DeviceSourceList)
        {
            for (int i = 1; i <= 2; i++)
            {
                LineSeries series = new()
                {
                    //Color = OxyColors.YellowGreen,
                    StrokeThickness = 2,
                    MarkerSize = 3,
                    //MarkerStroke = OxyColors.Green,
                    MarkerType = MarkerType.Circle,
                    Title = LineSeriesKey(item.Station, i.ToString()),
                };

                EnergyPlotModel.Series.Add(series);
            }
        }
    }

    #endregion

    #endregion

    #region privates

    private void ChangeDeviceConnState()
    {
        foreach (var device in DeviceSourceList)
        {
            var state = _deviceHealthManager.CanConnect(device.Line, device.Station);
            if (device.ConnectedState != state)
            {
                device.ConnectedState = state;
            }
        }
    }

    private string LineSeriesKey(string station, string category)
    {
        return $"{station} ({(category == "1" ? "有功" : "无功")})";
    }

    #endregion

    public void Dispose()
    {
        _cts.Cancel();
    }
}

public sealed class AlarmModel
{
    public string? Station { get; set; }

    public string? Name { get; set; }

    public DateTime CreatedAt { get; set; } = DateTime.Now;
}

public sealed class SpotCheckModel
{
    public string? Station { get; set; }

    public string? Tooling { get; set; }

    public string? Name { get; set; }

    public bool IsPass { get; set; }

    public DateTime CreatedAt { get; set; } = DateTime.Now;
}

public sealed class CardSwipingModel
{
    public string? Station { get; set; }

    public string? CardNo { get; set; }

    public string? Owner { get; set; }

    public string? CardDevice { get; set; }

    public DateTime CreatedAt { get; set; } = DateTime.Now;
}
